/* ********************************
 * 
 * author:  sunsc
 * date:    06/25/2013
 * update:  06/25/2013
 * file: 		riskMain.c
 * brief: Copyright (c) 2013 Sand
 * 
 ********************************/

#include "riskComm.h"


int 
main(int argc, char **argv)
{
		int nListenFd,nRet;
    int i=0;
    int nPort=8016,nPreChild=16,nMaxChild=256;
    pid_t pid=-1;
    char szFileName[FILENAMELEN];
    
    
	
		///init work date
		char szlocalDateTime[15];
		memset(szlocalDateTime,0x00,sizeof(szlocalDateTime));
		memset(szglobeDate,0x00,sizeof(szglobeDate));
		get_localHostTime(szlocalDateTime);
		memcpy(szglobeDate,szlocalDateTime,8);
		///init log system
	 	init_log(LOG_CFG);
		zlog_debug(zcGlobalLog,"log system start succeed.");
		///open&init sqlite3 database 
		nRet = sqlite3_open(DATA_FILE,&globeDb);
		if(nRet != 0){
			zlog_debug(zcGlobalLog,"open sqlite3 database failed.");
			sqlite3_close(globeDb);
			exit(-1);
		}	
		///init redis database serial NO.
		char *szerrMsg=NULL;
		nRet = sqlite3_exec(globeDb,"update sys_db set cur_db = 0,out_db = 1",NULL,0,&szerrMsg);
		if(nRet != SQLITE_OK){
			zlog_error(zcGlobalLog,"get rules failed:%s",szerrMsg);
			free(szerrMsg);
			return RISK_FAIL;
		}	
		free(szerrMsg);
		///get globe business rules from database
		zlog_debug(zcGlobalLog,"start to get busi rules.");
		nRet = 	get_busi_rules();
		if(nRet != 0){
			zlog_error(zcGlobalLog,"get business rules data failed.");
			return RISK_FAIL;
		}
#if TEST_FLAG
		zlog_debug(zcGlobalLog,"ChargeAmt: %d",sGlobeBusinessRules.nChargeAmt);
		zlog_debug(zcGlobalLog,"DeductAmt: %d",sGlobeBusinessRules.nDeductAmt);
		zlog_debug(zcGlobalLog,"GapTime: %d",sGlobeBusinessRules.nGapTime);
		zlog_debug(zcGlobalLog,"ProcessTime: %d",sGlobeBusinessRules.nProcessTime);
#endif	
		zlog_debug(zcGlobalLog,"get busi rules over.");
			
		signal(SIGCHLD,SIG_IGN);		
    ///direct to backend. 
    daemon_init();
    ///read config
    zlog_debug(zcGlobalLog,"start to read config.");
    memset(szFileName,0x00,sizeof(szFileName));
    memcpy(szFileName,FILE_ETC,sizeof(FILE_ETC));
    ReadInteger(szFileName,"RISK_CFG","port",&nPort);
    ReadInteger(szFileName,"RISK_CFG","prechild",&nPreChild);
    ReadInteger(szFileName,"RISK_CFG","maxchild",&nMaxChild);
    ///write to log
    zlog_debug(zcGlobalLog,"port: 		%d ",nPort);
    zlog_debug(zcGlobalLog,"prechild: %d ",nPreChild);
    zlog_debug(zcGlobalLog,"maxchild: %d ",nMaxChild);
    
    zlog_debug(zcGlobalLog,"read config over.");
    
		///listen to request	
    nListenFd=INET_Listen(nPort);
    if(nListenFd<0){
        zlog_error(zcGlobalLog,"listen the [%d] port failed.",nPort);
        exit(-1);
    }  
//procPool start:
   //keep only one running
	 if (write_pid() < 0){ 
    		zlog_warn(zcGlobalLog,"Another instance is running.");
        return -1; 
   }
   //init pipes... 
    if(pipe(fdParent) < 0){
        zlog_error(zcGlobalLog,"pipe failed");
        exit(-1);
    }
    if(pipe(fdChild) < 0){
        zlog_error(zcGlobalLog,"pipe failed");
        exit(-1);
    }
    //fork child process & init proc pool
    for(i=0;i<nPreChild;i++){
    	 if ((pid = fork()) < 0) {
	        zlog_error(zcGlobalLog,"fork faild");
	        exit(-1);
    	 }else if (pid == 0) {
        	fork_process(nListenFd);
    	 }else {
        	zlog_debug(zcGlobalLog,"have create child [%d]", pid);
       }     	
    }
    char task_end = TASK_END;
    char task_continue = TASK_CONTINUE;
    //child process requst number
    int req_num = 0;
    //child process number
    int child_num = nPreChild;
    pid_state_st pidState;
    while(1){
        //wait child process for sending message
        if (read(fdParent[0], &pidState, sizeof(pidState)) < sizeof(pidState)){
            zlog_error(zcGlobalLog,"father read pipe failed");
            exit(-1);
        }
        if (pidState.status == PID_BUSY){
            req_num++;
            //apply more child process       
            if (req_num > child_num && child_num < nMaxChild){ 
                if ((pid = fork()) < 0) {
                    zlog_error(zcGlobalLog,"fork faild");
                    exit(-1);
                }else if (pid == 0) {
                    fork_process(nListenFd);
                }else{
                    zlog_debug(zcGlobalLog,"have create child [%d]", pid);
                    child_num++;
                }        
            }
        }else if(pidState.status == PID_NOPE){
            req_num--;           
            if(child_num > (req_num + 1) && child_num > nPreChild){
              if (write(fdChild[1], &task_end, sizeof(task_end)) < sizeof(task_end)){
                  zlog_error(zcGlobalLog,"father write pipe failed");
                  exit(-1);
              }
            	child_num--;
            }else{
              	if(write(fdChild[1], &task_continue, sizeof(task_continue)) < sizeof(task_continue)){
                  zlog_error(zcGlobalLog,"father write pipe failed");
                  exit(-1);
              	}
            }            
        }
    }
	
	

	return 0;
}


